bitkeeper revision 1.1236.1.206 (424fd1e3OF1dIgDtN9JonRnCv2YHrQ)
authorkaf24@viper.(none) <kaf24@viper.(none)>
Sun, 3 Apr 2005 11:22:11 +0000 (11:22 +0000)
committerkaf24@viper.(none) <kaf24@viper.(none)>
Sun, 3 Apr 2005 11:22:11 +0000 (11:22 +0000)
Clean up symtab loading in elf loader.
Signed-off-by: Keir Fraser <keir@xensource.com>
tools/libxc/xc_linux_build.c
tools/libxc/xc_vmx_build.c
xen/arch/x86/domain_build.c
xen/common/elf.c
xen/include/xen/elf.h
xen/include/xen/sched.h

index 469861b786674aecad63d3b33d613140aa175e87..d4b28de06eb7d029668943a5faa183e3f3fa4aea 100644 (file)
@@ -22,8 +22,7 @@ struct domain_setup_info
     unsigned long v_kernend;
     unsigned long v_kernentry;
 
-    unsigned int load_bsd_symtab;
-
+    unsigned int  load_symtab;
     unsigned long symtab_addr;
     unsigned long symtab_len;
 };
@@ -34,7 +33,7 @@ parseelfimage(
 static int
 loadelfimage(
     char *elfbase, int xch, u32 dom, unsigned long *parray,
-    unsigned long vstart);
+    struct domain_setup_info *dsi);
 static int
 loadelfsymtab(
     char *elfbase, int xch, u32 dom, unsigned long *parray,
@@ -87,9 +86,6 @@ static int setup_guest(int xc_handle,
     if ( rc != 0 )
         goto error_out;
 
-    if (dsi.load_bsd_symtab)
-        loadelfsymtab(image, xc_handle, dom, NULL, &dsi);
-
     if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 )
     {
         PERROR("Guest OS must load to a page boundary.\n");
@@ -160,10 +156,7 @@ static int setup_guest(int xc_handle,
         goto error_out;
     }
 
-    loadelfimage(image, xc_handle, dom, page_array, dsi.v_start);
-
-    if (dsi.load_bsd_symtab)
-        loadelfsymtab(image, xc_handle, dom, page_array, &dsi);
+    loadelfimage(image, xc_handle, dom, page_array, &dsi);
 
     /* Load the initial ramdisk image. */
     if ( initrd_len != 0 )
@@ -581,21 +574,22 @@ static int parseelfimage(char *elfbase,
         dsi->v_start = strtoul(p+10, &p, 0);
 
     if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
-        dsi->load_bsd_symtab = 1;
+        dsi->load_symtab = 1;
 
     dsi->v_kernstart = kernstart;
     dsi->v_kernend   = kernend;
     dsi->v_kernentry = ehdr->e_entry;
-
     dsi->v_end       = dsi->v_kernend;
 
+    loadelfsymtab(elfbase, 0, 0, NULL, dsi);
+
     return 0;
 }
 
 static int
 loadelfimage(
     char *elfbase, int xch, u32 dom, unsigned long *parray,
-    unsigned long vstart)
+    struct domain_setup_info *dsi)
 {
     Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
     Elf_Phdr *phdr;
@@ -612,7 +606,7 @@ loadelfimage(
         
         for ( done = 0; done < phdr->p_filesz; done += chunksz )
         {
-            pa = (phdr->p_paddr + done) - vstart;
+            pa = (phdr->p_paddr + done) - dsi->v_start;
             va = xc_map_foreign_range(
                 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
             chunksz = phdr->p_filesz - done;
@@ -625,7 +619,7 @@ loadelfimage(
 
         for ( ; done < phdr->p_memsz; done += chunksz )
         {
-            pa = (phdr->p_paddr + done) - vstart;
+            pa = (phdr->p_paddr + done) - dsi->v_start;
             va = xc_map_foreign_range(
                 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
             chunksz = phdr->p_memsz - done;
@@ -636,6 +630,8 @@ loadelfimage(
         }
     }
 
+    loadelfsymtab(elfbase, xch, dom, parray, dsi);
+
     return 0;
 }
 
@@ -652,6 +648,9 @@ loadelfsymtab(
     char *p;
     int h, i;
 
+    if ( !dsi->load_symtab )
+        return 0;
+
     p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
                ehdr->e_shnum * sizeof(Elf_Shdr));
     if (p == NULL)
index ed9868e9f0ee20fe76f5e07ab644e1a8189b599a..dcd4f574f5e2258d48543ab622d6a6b1b3dfe86d 100644 (file)
@@ -26,11 +26,6 @@ struct domain_setup_info
     unsigned long v_kernstart;
     unsigned long v_kernend;
     unsigned long v_kernentry;
-
-    unsigned int load_bsd_symtab;
-
-    unsigned long symtab_addr;
-    unsigned long symtab_len;
 };
 
 static int
@@ -40,10 +35,6 @@ static int
 loadelfimage(
     char *elfbase, int xch, u32 dom, unsigned long *parray,
     unsigned long vstart);
-static int
-loadelfsymtab(
-    char *elfbase, int xch, u32 dom, unsigned long *parray,
-    struct domain_setup_info *dsi);
 
 static void build_e820map(struct mem_map *mem_mapp, unsigned long mem_size)
 {
@@ -193,13 +184,9 @@ static int setup_guest(int xc_handle,
 
     memset(&dsi, 0, sizeof(struct domain_setup_info));
 
-    rc = parseelfimage(image, image_size, &dsi);
-    if ( rc != 0 )
+    if ( (rc = parseelfimage(image, image_size, &dsi)) != 0 )
         goto error_out;
 
-    if (dsi.load_bsd_symtab)
-        loadelfsymtab(image, xc_handle, dom, NULL, &dsi);
-
     if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 )
     {
         PERROR("Guest OS must load to a page boundary.\n");
@@ -269,9 +256,6 @@ static int setup_guest(int xc_handle,
 
     loadelfimage(image, xc_handle, dom, page_array, dsi.v_start);
 
-    if (dsi.load_bsd_symtab)
-        loadelfsymtab(image, xc_handle, dom, page_array, &dsi);
-
     /* Load the initial ramdisk image. */
     if ( initrd_len != 0 )
     {
@@ -708,7 +692,6 @@ static int parseelfimage(char *elfbase,
     }
 
     dsi->v_start = 0x00000000;
-    dsi->load_bsd_symtab = 0;
 
     dsi->v_kernstart = kernstart - LINUX_PAGE_OFFSET;
     dsi->v_kernend   = kernend - LINUX_PAGE_OFFSET;
@@ -769,101 +752,3 @@ loadelfimage(
 
     return 0;
 }
-
-
-#define ELFROUND (ELFSIZE / 8)
-
-static int
-loadelfsymtab(
-    char *elfbase, int xch, u32 dom, unsigned long *parray,
-    struct domain_setup_info *dsi)
-{
-    Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase, *sym_ehdr;
-    Elf_Shdr *shdr;
-    unsigned long maxva, symva;
-    char *p;
-    int h, i;
-
-    p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
-               ehdr->e_shnum * sizeof(Elf_Shdr));
-    if (p == NULL)
-        return 0;
-
-    maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
-    symva = maxva;
-    maxva += sizeof(int);
-    dsi->symtab_addr = maxva;
-    dsi->symtab_len = 0;
-    maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
-    maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
-
-    shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
-    memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
-
-    for ( h = 0; h < ehdr->e_shnum; h++ ) 
-    {
-        if ( shdr[h].sh_type == SHT_STRTAB )
-        {
-            /* Look for a strtab @i linked to symtab @h. */
-            for ( i = 0; i < ehdr->e_shnum; i++ )
-                if ( (shdr[i].sh_type == SHT_SYMTAB) &&
-                     (shdr[i].sh_link == h) )
-                    break;
-            /* Skip symtab @h if we found no corresponding strtab @i. */
-            if ( i == ehdr->e_shnum )
-            {
-                shdr[h].sh_offset = 0;
-                continue;
-            }
-        }
-
-        if ( (shdr[h].sh_type == SHT_STRTAB) ||
-             (shdr[h].sh_type == SHT_SYMTAB) )
-        {
-            if ( parray != NULL )
-                xc_map_memcpy(maxva, elfbase + shdr[h].sh_offset, shdr[h].sh_size,
-                           xch, dom, parray, dsi->v_start);
-
-            /* Mangled to be based on ELF header location. */
-            shdr[h].sh_offset = maxva - dsi->symtab_addr;
-
-            dsi->symtab_len += shdr[h].sh_size;
-            maxva += shdr[h].sh_size;
-            maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
-        }
-
-        shdr[h].sh_name = 0;  /* Name is NULL. */
-    }
-
-    if ( dsi->symtab_len == 0 )
-    {
-        dsi->symtab_addr = 0;
-        goto out;
-    }
-
-    if ( parray != NULL )
-    {
-        *(int *)p = maxva - dsi->symtab_addr;
-        sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
-        memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
-        sym_ehdr->e_phoff = 0;
-        sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
-        sym_ehdr->e_phentsize = 0;
-        sym_ehdr->e_phnum = 0;
-        sym_ehdr->e_shstrndx = SHN_UNDEF;
-
-        /* Copy total length, crafted ELF header and section header table */
-        xc_map_memcpy(symva, p, sizeof(int) + sizeof(Elf_Ehdr) +
-                   ehdr->e_shnum * sizeof(Elf_Shdr), xch, dom, parray,
-                   dsi->v_start);
-    }
-
-    dsi->symtab_len = maxva - dsi->symtab_addr;
-    dsi->v_end = round_pgup(maxva);
-
- out:
-    if ( p != NULL )
-        free(p);
-
-    return 0;
-}
index d896df6ad7dcec9f09bb6bbfc6ec929e7a82533a..b7c8156dfd8aac79f77785e7dc17c29d6921479e 100644 (file)
@@ -111,6 +111,8 @@ int construct_dom0(struct domain *d,
         BUG();
 
     memset(&dsi, 0, sizeof(struct domain_setup_info));
+    dsi.image_addr = (unsigned long)image_start;
+    dsi.image_len  = image_len;
 
     printk("*** LOADING DOMAIN 0 ***\n");
 
@@ -125,13 +127,9 @@ int construct_dom0(struct domain *d,
     alloc_start = page_to_phys(page);
     alloc_end   = alloc_start + (d->tot_pages << PAGE_SHIFT);
     
-    rc = parseelfimage(image_start, image_len, &dsi);
-    if ( rc != 0 )
+    if ( (rc = parseelfimage(&dsi)) != 0 )
         return rc;
 
-    if (dsi.load_bsd_symtab)
-        loadelfsymtab(image_start, 0, &dsi);
-
     /* Align load address to 4MB boundary. */
     dsi.v_start &= ~((1UL<<22)-1);
 
@@ -424,10 +422,7 @@ int construct_dom0(struct domain *d,
     write_ptbase(ed);
 
     /* Copy the OS image and free temporary buffer. */
-    (void)loadelfimage(image_start);
-
-    if (dsi.load_bsd_symtab)
-        loadelfsymtab(image_start, 1, &dsi);
+    (void)loadelfimage(&dsi);
 
     init_domheap_pages(
         _image_start, (_image_start+image_len+PAGE_SIZE-1) & PAGE_MASK);
index 1302acfdea499482dc88a773ef23b96f3582b77e..98f9565e2da7745dd956c2b7fb1c4a8a29698e8c 100644 (file)
 #define FORCE_XENELF_IMAGE 0
 #endif
 
+static void loadelfsymtab(struct domain_setup_info *dsi, int doload);
 static inline int is_loadable_phdr(Elf_Phdr *phdr)
 {
     return ((phdr->p_type == PT_LOAD) &&
             ((phdr->p_flags & (PF_W|PF_X)) != 0));
 }
 
-int parseelfimage(char *elfbase, 
-                  unsigned long elfsize,
-                  struct domain_setup_info *dsi)
+int parseelfimage(struct domain_setup_info *dsi)
 {
-    Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
+    Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr;
     Elf_Phdr *phdr;
     Elf_Shdr *shdr;
     unsigned long kernstart = ~0UL, kernend=0UL;
     char *shstrtab, *guestinfo=NULL, *p;
+    char *elfbase = (char *)dsi->image_addr;
     int h;
 
     if ( !elf_sanity_check(ehdr) )
         return -EINVAL;
 
-    if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize )
+    if ( (ehdr->e_phoff + (ehdr->e_phnum*ehdr->e_phentsize)) > dsi->image_len )
     {
         printk("ELF program headers extend beyond end of image.\n");
         return -EINVAL;
     }
 
-    if ( (ehdr->e_shoff + (ehdr->e_shnum * ehdr->e_shentsize)) > elfsize )
+    if ( (ehdr->e_shoff + (ehdr->e_shnum*ehdr->e_shentsize)) > dsi->image_len )
     {
         printk("ELF section headers extend beyond end of image.\n");
         return -EINVAL;
@@ -120,22 +120,23 @@ int parseelfimage(char *elfbase,
             dsi->v_start = simple_strtoul(p+10, &p, 0);
 
         if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
-            dsi->load_bsd_symtab = 1;
-
+            dsi->load_symtab = 1;
     }
 
     dsi->v_kernstart = kernstart;
     dsi->v_kernend   = kernend;
     dsi->v_kernentry = ehdr->e_entry;
-
     dsi->v_end       = dsi->v_kernend;
 
+    loadelfsymtab(dsi, 0);
+
     return 0;
 }
 
-int loadelfimage(char *elfbase)
+int loadelfimage(struct domain_setup_info *dsi)
 {
-    Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
+    char *elfbase = (char *)dsi->image_addr;
+    Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr;
     Elf_Phdr *phdr;
     int h;
   
@@ -152,19 +153,24 @@ int loadelfimage(char *elfbase)
                    phdr->p_memsz - phdr->p_filesz);
     }
 
+    loadelfsymtab(dsi, 1);
+
     return 0;
 }
 
 #define ELFROUND (ELFSIZE / 8)
 
-int loadelfsymtab(char *elfbase, int doload, struct domain_setup_info *dsi)
+static void loadelfsymtab(struct domain_setup_info *dsi, int doload)
 {
-    Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase, *sym_ehdr;
+    Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr, *sym_ehdr;
     Elf_Shdr *shdr;
     unsigned long maxva, symva;
-    char *p;
+    char *p, *elfbase = (char *)dsi->image_addr;
     int h, i;
 
+    if ( !dsi->load_symtab )
+        return;
+
     maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
     symva = maxva;
     maxva += sizeof(int);
@@ -172,14 +178,16 @@ int loadelfsymtab(char *elfbase, int doload, struct domain_setup_info *dsi)
     dsi->symtab_len = 0;
     maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
     maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
-    if (doload) {
-       p = (void *)symva;
-
-       shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
-       memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
-    } else {
-       shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff);
-       p = NULL; /* XXX: gcc */
+    if ( doload )
+    {
+        p = (void *)symva;
+        shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
+        memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum*sizeof(Elf_Shdr));
+    } 
+    else
+    {
+        p = NULL;
+        shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff);
     }
 
     for ( h = 0; h < ehdr->e_shnum; h++ ) 
@@ -194,9 +202,9 @@ int loadelfsymtab(char *elfbase, int doload, struct domain_setup_info *dsi)
             /* Skip symtab @h if we found no corresponding strtab @i. */
             if ( i == ehdr->e_shnum )
             {
-               if (doload) {
-                   shdr[h].sh_offset = 0;
-               }
+                if (doload) {
+                    shdr[h].sh_offset = 0;
+                }
                 continue;
             }
         }
@@ -204,49 +212,43 @@ int loadelfsymtab(char *elfbase, int doload, struct domain_setup_info *dsi)
         if ( (shdr[h].sh_type == SHT_STRTAB) ||
              (shdr[h].sh_type == SHT_SYMTAB) )
         {
-           if (doload) {
-               memcpy((void *)maxva, elfbase + shdr[h].sh_offset,
-                   shdr[h].sh_size);
+            if (doload) {
+                memcpy((void *)maxva, elfbase + shdr[h].sh_offset,
+                       shdr[h].sh_size);
 
-               /* Mangled to be based on ELF header location. */
-               shdr[h].sh_offset = maxva - dsi->symtab_addr;
+                /* Mangled to be based on ELF header location. */
+                shdr[h].sh_offset = maxva - dsi->symtab_addr;
 
-           }
-           dsi->symtab_len += shdr[h].sh_size;
-           maxva += shdr[h].sh_size;
-           maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
+            }
+            dsi->symtab_len += shdr[h].sh_size;
+            maxva += shdr[h].sh_size;
+            maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
         }
 
-        if (doload) {
-           shdr[h].sh_name = 0;  /* Name is NULL. */
-       }
+        if ( doload )
+            shdr[h].sh_name = 0;  /* Name is NULL. */
     }
 
     if ( dsi->symtab_len == 0 )
     {
         dsi->symtab_addr = 0;
-        goto out;
+        return;
     }
 
-    if (doload) {
-       *(int *)p = maxva - dsi->symtab_addr;
-       sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
-       memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
-       sym_ehdr->e_phoff = 0;
-       sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
-       sym_ehdr->e_phentsize = 0;
-       sym_ehdr->e_phnum = 0;
-       sym_ehdr->e_shstrndx = SHN_UNDEF;
+    if ( doload )
+    {
+        *(int *)p = maxva - dsi->symtab_addr;
+        sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
+        memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
+        sym_ehdr->e_phoff = 0;
+        sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
+        sym_ehdr->e_phentsize = 0;
+        sym_ehdr->e_phnum = 0;
+        sym_ehdr->e_shstrndx = SHN_UNDEF;
     }
 
-#define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK) /* XXX */
-
     dsi->symtab_len = maxva - dsi->symtab_addr;
-    dsi->v_end = round_pgup(maxva);
-
- out:
-
-    return 0;
+    dsi->v_end      = maxva;
 }
 
 /*
index 0b98390ed591b68e745e818b9d3d5d2582c33949..1d2ac6919a506fd53efbfefbd35c1561f0317b6e 100644 (file)
@@ -526,9 +526,8 @@ typedef struct {
 #endif
 
 struct domain_setup_info;
-extern int loadelfimage(char *);
-extern int loadelfsymtab(char *, int, struct domain_setup_info *);
-extern int parseelfimage(char *, unsigned long, struct domain_setup_info *);
+extern int loadelfimage(struct domain_setup_info *);
+extern int parseelfimage(struct domain_setup_info *);
 
 #ifdef Elf_Ehdr
 extern int elf_sanity_check(Elf_Ehdr *ehdr);
index ac783669d15cd3e88104d99885297ff15b4f0b8c..2352a82c0951ca10d34f1777d64f9b21d37fa367 100644 (file)
@@ -151,14 +151,17 @@ struct domain
 
 struct domain_setup_info
 {
+    /* Initialised by caller. */
+    unsigned long image_addr;
+    unsigned long image_len;
+    /* Initialised by loader: Public. */
     unsigned long v_start;
     unsigned long v_end;
     unsigned long v_kernstart;
     unsigned long v_kernend;
     unsigned long v_kernentry;
-
-    unsigned int load_bsd_symtab;
-
+    /* Initialised by loader: Private. */
+    unsigned int  load_symtab;
     unsigned long symtab_addr;
     unsigned long symtab_len;
 };